package cn.xiaolang.function.quartz;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

/**
 * 调度器工具类，把调度任务加入到调度容器中，执行调度容器中所有的任务
 * @version 1.0
 * @since JDK1.7
 * @author fuhw
 * @date 2016年3月31日 上午10:49:22
 */
public enum SchedulerUtils {
	schedulers;
	//初始化一个存放调度器的容器
	private Map<JobDetail,Trigger> schedulerMap = new HashMap<>();
	
	/**
	 * 添加一个按cron表达式触发的调度器
	 * (调用名，job.getName()+"_job"形式)
	 * @param job 任务job的Class对象，必须是Job的子类
	 * @param cronExpression 触发器执行认为的规则表达式
	 * @param params 任务详情携带的参数集合JobDataMap
	 * @param group 调度的组名
	 * 
	 * @author fuhw
	 * @date 2016年3月31日 上午10:57:18
	 */
	public void addScheduler(Class<? extends Job> job,String cronExpression,Map<String, Object> params,String group){
		if(group == null){
			group = "system_group";//传入组名为空，设置为默认组名
		}
		JobDetail jobDetail = JobBuilder.newJob(job)//实例化一个任务
				.withIdentity(job.getName()+"_job", group).build();
		if(params != null && !params.isEmpty()){//传入参数不为空，加入到JobDataMap中
			jobDetail.getJobDataMap().putAll(params);
		}
		//创建一个触发器
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getName()+"_trigger", group)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionFireAndProceed()).build();
		//添加到调度器容器中
		schedulerMap.put(jobDetail, trigger);
	}
	
	public void addScheduler(Class<? extends Job> job,String cronExpression){
		addScheduler(job, cronExpression, null, null);
	}

	public void addScheduler(Class<? extends Job> job,String cronExpression,Map<String, Object> params){
		addScheduler(job, cronExpression, params, null);
	}
	
	public void addScheduler(Class<? extends Job> job,String cronExpression,String group){
		addScheduler(job, cronExpression, null, group);
	}
	/**
	 * 携带单个参数（key,value）
	 * 组名默认设置为“system_group”
	 * @param job
	 * @param cronExpression
	 * @param key
	 * @param value
	 * @param group
	 * 
	 * @author fuhw
	 * @date 2016年3月31日 上午11:17:35
	 */
	public void addScheduler(Class<? extends Job> job, String cronExpression, String key, Object value, String group) {
		if(group == null){
			group = "system_group";//传入组名为空，设置为默认组名
		}
		JobDetail jobDetail = JobBuilder.newJob(job)
				.withIdentity(job.getName() + "_job", group).build();
		if (key != null && value != null) {
			jobDetail.getJobDataMap().put(key, value);
		}
		/**
		 * withMisfireHandlingInstructionDoNothing
			——不触发立即执行
			——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
			withMisfireHandlingInstructionIgnoreMisfires
			——以错过的第一个频率时间立刻开始执行
			——重做错过的所有频率周期后
			——当下一次触发频率发生时间大于当前时间后，再按照正常的Cron频率依次执行
			withMisfireHandlingInstructionFireAndProceed
			——以当前时间为触发频率立刻触发一次执行
			——然后按照Cron频率依次执行
		 */
		Trigger trigger = TriggerBuilder
				.newTrigger().withIdentity(job.getName() + "_trigger", group)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)
						.withMisfireHandlingInstructionFireAndProceed()).build();
		schedulerMap.put(jobDetail, trigger);
	}
	//========================立即执行的job任务=======================
	/**
	 * 添加一个立即触发的调度器
	 * (调用名，job.getName()+"_job"形式)
	 * @param job 任务job的Class对象，必须是Job的子类
	 * @param params 任务详情携带的参数集合JobDataMap
	 * @param group 调度的组名
	 * 
	 * @author fuhw
	 * @date 2016年3月31日 上午11:23:56
	 */
	public void addSchedulerStartNow(Class<? extends Job> job,Map<String, Object> params,String group){
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(job)
				.withIdentity(job.getName()+"_job", group).build();
		if(params != null && !params.isEmpty()){
			jobDetail.getJobDataMap().putAll(params);
		}
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getName()+"_trigger", group)
				.startNow().build();//立即触发
		schedulerMap.put(jobDetail, trigger);
	}
	public void addSchedulerStartNow(Class<? extends Job> job,Map<String, Object> params){
		addSchedulerStartNow(job, params, null);
	}
	public void addSchedulerStartNow(Class<? extends Job> job,String group){
		addSchedulerStartNow(job, null, group);
	}
	public void addSchedulerStartNow(Class<? extends Job> job){
		addSchedulerStartNow(job, null, null);
	}
	
	/**
	 * 添加一个立即触发的调度器
	 * 携带单个参数（key,value）
	 * 组名默认设置为“system_group”
	 * @param job
	 * @param key
	 * @param value
	 * @param group
	 * 
	 * @author fuhw
	 * @date 2016年3月31日 下午12:18:53
	 */
	public void addSchedulerStartNow(Class<? extends Job> job, String key, Object value, String group) {
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(job)
				.withIdentity(job.getName() + "_job", group).build();
		if (key != null && value != null) {
			jobDetail.getJobDataMap().put(key, value);
		}
		Trigger trigger = TriggerBuilder
				.newTrigger().withIdentity(job.getName() + "_trigger", group)
				.startNow().build();
		schedulerMap.put(jobDetail, trigger);
	}
	
	
	//======================controller job===========================
	private static final String controller_key = "_controller_class";
	/**
	 * 添加一个调度crontoller的调度器(集合参数Map<String,Object>)
	 * 
	 * @param controller 任务实例controller
	 * @param cronExpression 触发规则cron表达式
	 * @param params 任务job携带的参数
	 * @param group 任务分组名称
	 * 
	 * @author fuhw
	 * @date 2016年3月31日 下午1:17:29
	 */
	public void addControllerScheduler(Class<?> controller,String cronExpression,Map<String, Object> params,String group){
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(ControllerEngineJob.class)
				.withIdentity(controller.getName()+"_job", group).build();
		if(params != null && !params.isEmpty()){
			jobDetail.getJobDataMap().putAll(params);
		}
		jobDetail.getJobDataMap().put(controller_key, controller);//把要执行的controller作为参数，给ControllerEngineJob调度执行
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(controller.getName()+"_trigger", group)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)
						.withMisfireHandlingInstructionFireAndProceed()).build();
	    schedulerMap.put(jobDetail, trigger);
	}
	
	
	public void addControllerScheduler(Class<?> controller,String cronExpression,Map<String, Object> params){
		addControllerScheduler(controller, cronExpression, params,null);
	}
	public void addControllerScheduler(Class<?> controller,String cronExpression){
		addControllerScheduler(controller, cronExpression, null,null);
	}
	public void addControllerScheduler(Class<?> controller,String cronExpression,String group){
		addControllerScheduler(controller, cronExpression, null,group);
	}
	/**
	 * 添加一个调度crontoller的调度器(单个参数key-value)
	 * 
	 * @param controller 任务实例controller
	 * @param cronExpression 触发规则cron表达式
	 * @param params 任务job携带的参数
	 * @param group 任务分组名称
	 * 
	 * @author fuhw
	 */
	public void addControllerScheduler(Class<?> controller,String cronExpression,String key,Object value,String group){
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(ControllerEngineJob.class)
				.withIdentity(controller.getName()+"_job", group).build();
		if(key != null && value != null){
			jobDetail.getJobDataMap().put(key,value);
		}
		jobDetail.getJobDataMap().put(controller_key, controller);//把要执行的controller作为参数，给ControllerEngineJob调度执行
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(controller.getName()+"_trigger", group)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)
						.withMisfireHandlingInstructionFireAndProceed()).build();
	    schedulerMap.put(jobDetail, trigger);
	}
	
	//===============立即启动的Controller任务调度======================
	public void addControllerSchedulerStartNow(Class<?> controller,Map<String, Object> params,String group){
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(ControllerEngineJob.class)
				.withIdentity(controller.getName()+"_job", group).build();
		if(params != null && !params.isEmpty()){
			jobDetail.getJobDataMap().putAll(params);
		}
		jobDetail.getJobDataMap().put(controller_key, controller);//把要执行的controller作为参数，给ControllerEngineJob调度执行
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(controller.getName()+"_trigger", group)
				.startNow().build();
	    schedulerMap.put(jobDetail, trigger);
	}
	
	public void addControllerSchedulerStartNow(Class<?> controller,Map<String, Object> params){
		addControllerSchedulerStartNow(controller, params, null);
	}
	public void addControllerSchedulerStartNow(Class<?> controller,String group){
		addControllerSchedulerStartNow(controller, null, group);
	}
	public void addControllerSchedulerStartNow(Class<?> controller){
		addControllerSchedulerStartNow(controller, null, null);
	}
	
	public void addControllerSchedulerStartNow(Class<?> controller,String key ,Object value,String group){
		if(group == null){
			group = "system_group";
		}
		JobDetail jobDetail = JobBuilder.newJob(ControllerEngineJob.class)
				.withIdentity(controller.getName()+"_job", group).build();
		if(key != null && value != null){
			jobDetail.getJobDataMap().put(key, value);
		}
		jobDetail.getJobDataMap().put(controller_key, controller);//把要执行的controller作为参数，给ControllerEngineJob调度执行
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(controller.getName()+"_trigger", group)
				.startNow().build();
	    schedulerMap.put(jobDetail, trigger);
	}
	
	/**
	 * 
	 * 执行调度容器中的所有调度任务 
	 * @author fuhw
	 * @date 2016年3月31日 下午3:37:49
	 */
	public void start(){
		if(schedulerMap.isEmpty()){
			return;//如果容器中没有调度任务直接返回
		}
		SchedulerFactory schedulerFactory = new StdSchedulerFactory();
		try {
			Scheduler scheduler = schedulerFactory.getScheduler();//获取调度器
			for(Entry<JobDetail, Trigger> entry:schedulerMap.entrySet()){
				scheduler.scheduleJob(entry.getKey(), entry.getValue());//调用器，从调度任务容器中，加载JobDetail,Trigger
				scheduler.start();
			}
			
		} catch (SchedulerException e) {
			e.printStackTrace();
		}finally{
			System.gc();
		}
		
	}
}
